summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/pla.c
blob: 28c1609e11a62cd4aeb0ddcbe4cce6b4bb3757ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**********************************************************************

    PLS100 16x48x8 Programmable Logic Array emulation

    Copyright MESS Team.
    Visit http://mamedev.org for licensing and usage restrictions.

**********************************************************************/

#include "pla.h"



//**************************************************************************
//  DEVICE TYPE DEFINITION
//**************************************************************************

const device_type PLS100 = &device_creator<pls100_device>;
const device_type MOS8721 = &device_creator<mos8721_device>;



//**************************************************************************
//  INLINE HELPERS
//**************************************************************************

//-------------------------------------------------
//  parse_fusemap -
//-------------------------------------------------

inline void pla_device::parse_fusemap()
{
	jed_data jed;
	jedbin_parse(machine().root_device().memregion(tag())->base(), machine().root_device().memregion(tag())->bytes(), &jed);
	UINT32 fusenum = 0;
	m_xor = 0;

	for (int term = 0; term < m_terms; term++)
	{
		m_and_comp[term] = 0;
		m_and_true[term] = 0;
		m_or[term] = 0;

		for (int i = 0; i < m_inputs; i++)
		{
			m_and_comp[term] |= jed_get_fuse(&jed, fusenum++) << i;
			m_and_true[term] |= jed_get_fuse(&jed, fusenum++) << i;
		}

		for (int f = 0; f < m_outputs; f++)
		{
			m_or[term] |= !jed_get_fuse(&jed, fusenum++) << f;
		}
	}

	for (int f = 0; f < m_outputs; f++)
	{
		m_xor |= jed_get_fuse(&jed, fusenum++) << f;
	}
}


//-------------------------------------------------
//  get_product -
//-------------------------------------------------

inline int pla_device::get_product(int term)
{
	UINT32 input_true = m_and_true[term] | m_i;
	UINT32 input_comp = m_and_comp[term] | ~m_i;

	return ((input_true & input_comp) & m_output_mask) == m_output_mask;
}


//-------------------------------------------------
//  update_outputs -
//-------------------------------------------------

inline void pla_device::update_outputs()
{
	m_s = 0;

	for (int term = 0; term < m_terms; term++)
	{
		if (get_product(term))
		{
			m_s |= m_or[term];
		}
	}
}



//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  pla_device - constructor
//-------------------------------------------------

pla_device::pla_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int inputs, int outputs, int terms, UINT32 output_mask)
	: device_t(mconfig, type, name, tag, owner, clock),
	  m_inputs(inputs),
	  m_outputs(outputs),
	  m_terms(terms),
	  m_output_mask(output_mask)
{
}

pls100_device::pls100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
    : pla_device(mconfig, PLS100, "PLS100", tag, owner, clock, 16, 8, 48, 0xffff)
{
}

mos8721_device::mos8721_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
    : pla_device(mconfig, MOS8721, "MOS8721", tag, owner, clock, 27, 18, 48, 0x7ffffff)
{
}


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void pla_device::device_start()
{
	// parse fusemap
	assert(machine().root_device().memregion(tag()) != NULL);
	parse_fusemap();

	// register for state saving
	save_item(NAME(m_i));
	save_item(NAME(m_s));
}


//-------------------------------------------------
//  read -
//-------------------------------------------------

UINT32 pla_device::read(UINT32 input)
{
	m_i = input;

	update_outputs();

	return m_s ^ m_xor;
}