Skip to content

Commit 78a49ea

Browse files
committed
Merge branch 'master' of github.com:steveicarus/iverilog
2 parents 1784488 + dbaf247 commit 78a49ea

31 files changed

+604
-83
lines changed

design_dump.cc

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
2+
* Copyright (c) 1998-2016 Stephen Williams ([email protected])
33
*
44
* This source code is free software; you can redistribute it
55
* and/or modify it in source code form under the terms of the GNU
@@ -688,6 +688,14 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
688688
dump_obj_attr(o, ind+4);
689689
}
690690

691+
void NetLatch::dump_node(ostream&o, unsigned ind) const
692+
{
693+
o << setw(ind) << "" << "LPM_LATCH: " << name()
694+
<< " scope=" << scope_path(scope()) << endl;
695+
dump_node_pins(o, ind+4);
696+
dump_obj_attr(o, ind+4);
697+
}
698+
691699
void NetLiteral::dump_node(ostream&o, unsigned ind) const
692700
{
693701
o << setw(ind) << "" << "constant real " << real_

elaborate.cc

+10-15
Original file line numberDiff line numberDiff line change
@@ -1408,7 +1408,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
14081408
// that connects to the port.
14091409

14101410
NetNet*sig = 0;
1411-
if (prts.empty() || (prts[0]->port_type() == NetNet::PINPUT)) {
1411+
NetNet::PortType ptype = prts[0]->port_type();
1412+
if (prts.empty() || (ptype == NetNet::PINPUT)) {
14121413

14131414
// Special case: If the input port is an unpacked
14141415
// array, then there should be no sub-ports and
@@ -1501,7 +1502,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
15011502
sig->vector_width());
15021503
}
15031504

1504-
} else if (prts[0]->port_type() == NetNet::PINOUT) {
1505+
} else if (ptype == NetNet::PINOUT) {
15051506

15061507
// For now, do not support unpacked array outputs.
15071508
ivl_assert(*this, prts[0]->unpacked_dimensions()==0);
@@ -1562,7 +1563,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
15621563
} else {
15631564

15641565
/* Port type must be OUTPUT here. */
1565-
ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT);
1566+
ivl_assert(*this, ptype == NetNet::POUTPUT);
15661567

15671568
// Special case: If the output port is an unpacked
15681569
// array, then there should be no sub-ports and
@@ -1625,11 +1626,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
16251626
}
16261627
prts_vector_width = sig->vector_width();
16271628
for (unsigned pidx = 0; pidx < prts.size(); pidx += 1) {
1628-
prts[pidx]->port_type(NetNet::NOT_A_PORT);
16291629
prts[pidx] = cast_to_int4(des, scope, prts[pidx],
16301630
prts_vector_width /
16311631
instance.size());
1632-
prts[pidx]->port_type(NetNet::POUTPUT);
16331632
}
16341633
}
16351634

@@ -1638,9 +1637,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
16381637
if ((sig->data_type() == IVL_VT_REAL ) &&
16391638
!prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) {
16401639
prts_vector_width -= prts[0]->vector_width() - 1;
1641-
prts[0]->port_type(NetNet::NOT_A_PORT);
16421640
prts[0] = cast_to_real(des, scope, prts[0]);
1643-
prts[0]->port_type(NetNet::POUTPUT);
16441641
// No support for multiple real drivers.
16451642
if (instance.size() != 1) {
16461643
cerr << pins[idx]->get_fileline() << ": error: "
@@ -1658,10 +1655,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
16581655
if ((sig->data_type() == IVL_VT_BOOL ) &&
16591656
!prts.empty() && (prts[0]->data_type() == IVL_VT_LOGIC )) {
16601657
for (unsigned pidx = 0; pidx < prts.size(); pidx += 1) {
1661-
prts[pidx]->port_type(NetNet::NOT_A_PORT);
16621658
prts[pidx] = cast_to_int2(des, scope, prts[pidx],
16631659
prts[pidx]->vector_width());
1664-
prts[pidx]->port_type(NetNet::POUTPUT);
16651660
}
16661661
}
16671662

@@ -1685,7 +1680,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
16851680

16861681
#ifndef NDEBUG
16871682
if ((! prts.empty())
1688-
&& (prts[0]->port_type() != NetNet::PINPUT)) {
1683+
&& (ptype != NetNet::PINPUT)) {
16891684
assert(sig->type() != NetNet::REG);
16901685
}
16911686
#endif
@@ -1718,7 +1713,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
17181713
&& (prts_vector_width != sig->vector_width())) {
17191714
bool as_signed = false;
17201715

1721-
switch (prts[0]->port_type()) {
1716+
switch (ptype) {
17221717
case NetNet::POUTPUT:
17231718
as_signed = prts[0]->get_signed();
17241719
break;
@@ -1742,7 +1737,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
17421737
" bits, got " << sig->vector_width() << "." << endl;
17431738

17441739
// Delete this when inout ports pad correctly.
1745-
if (prts[0]->port_type() == NetNet::PINOUT) {
1740+
if (ptype == NetNet::PINOUT) {
17461741
if (prts_vector_width > sig->vector_width()) {
17471742
cerr << get_fileline() << ": : Leaving "
17481743
<< (prts_vector_width-sig->vector_width())
@@ -1762,7 +1757,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
17621757
<< " high bits of the port."
17631758
<< endl;
17641759
} else {
1765-
if (prts[0]->port_type() == NetNet::PINPUT) {
1760+
if (ptype == NetNet::PINPUT) {
17661761
cerr << get_fileline() << ": : Pruning ";
17671762
} else {
17681763
cerr << get_fileline() << ": : Padding ";
@@ -1774,7 +1769,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
17741769
}
17751770

17761771
sig = resize_net_to_port_(des, scope, sig, prts_vector_width,
1777-
prts[0]->port_type(), as_signed);
1772+
ptype, as_signed);
17781773
}
17791774

17801775
// Connect the sig expression that is the context of the
@@ -1825,7 +1820,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
18251820
for (unsigned ldx = 0 ; ldx < prts.size() ; ldx += 1)
18261821
connect(prts[ldx]->pin(0), sig->pin(0));
18271822

1828-
} else switch (prts[0]->port_type()) {
1823+
} else switch (ptype) {
18291824
case NetNet::POUTPUT:
18301825
ctmp = new NetConcat(scope, scope->local_symbol(),
18311826
prts_vector_width, prts.size());

emit.cc

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2013 Stephen Williams ([email protected])
2+
* Copyright (c) 1998-2016 Stephen Williams ([email protected])
33
*
44
* This source code is free software; you can redistribute it
55
* and/or modify it in source code form under the terms of the GNU
@@ -123,6 +123,12 @@ bool NetFF::emit_node(struct target_t*tgt) const
123123
return true;
124124
}
125125

126+
bool NetLatch::emit_node(struct target_t*tgt) const
127+
{
128+
tgt->lpm_latch(this);
129+
return true;
130+
}
131+
126132
bool NetLiteral::emit_node(struct target_t*tgt) const
127133
{
128134
return tgt->net_literal(this);

functor.cc

+9
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ void functor_t::lpm_ff(Design*, NetFF*)
7878
{
7979
}
8080

81+
void functor_t::lpm_latch(Design*, NetLatch*)
82+
{
83+
}
84+
8185
void functor_t::lpm_logic(Design*, NetLogic*)
8286
{
8387
}
@@ -219,6 +223,11 @@ void NetFF::functor_node(Design*des, functor_t*fun)
219223
fun->lpm_ff(des, this);
220224
}
221225

226+
void NetLatch::functor_node(Design*des, functor_t*fun)
227+
{
228+
fun->lpm_latch(des, this);
229+
}
230+
222231
void NetLiteral::functor_node(Design*des, functor_t*fun)
223232
{
224233
fun->lpm_literal(des, this);

functor.h

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ struct functor_t {
7575
/* This method is called for each FF in the design. */
7676
virtual void lpm_ff(class Design*des, class NetFF*);
7777

78+
/* This method is called for each LATCH in the design. */
79+
virtual void lpm_latch(class Design*des, class NetLatch*);
80+
7881
/* Handle LPM combinational logic devices. */
7982
virtual void lpm_logic(class Design*des, class NetLogic*);
8083

ivl_target.h

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef IVL_ivl_target_H
22
#define IVL_ivl_target_H
33
/*
4-
* Copyright (c) 2000-2015 Stephen Williams ([email protected])
4+
* Copyright (c) 2000-2016 Stephen Williams ([email protected])
55
*
66
* This source code is free software; you can redistribute it
77
* and/or modify it in source code form under the terms of the GNU
@@ -315,6 +315,7 @@ typedef enum ivl_lpm_type_e {
315315
IVL_LPM_CMP_NEE= 19, /* Case NE (!==) */
316316
IVL_LPM_DIVIDE = 12,
317317
IVL_LPM_FF = 3,
318+
IVL_LPM_LATCH = 40,
318319
IVL_LPM_MOD = 13,
319320
IVL_LPM_MULT = 4,
320321
IVL_LPM_MUX = 5,
@@ -1309,8 +1310,13 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
13091310
* inputs and the Q. All the types must be exactly the same.
13101311
*
13111312
* - D-FlipFlop (IVL_LPM_FF)
1312-
* This data is an edge sensitive register. The ivl_lpm_q output and
1313-
* single ivl_lpm_data input are the same with, ivl_lpm_width. This
1313+
* This device is an edge sensitive register. The ivl_lpm_q output and
1314+
* single ivl_lpm_data input are the same width, ivl_lpm_width. This
1315+
* device carries a vector like other LPM devices.
1316+
*
1317+
* - Latch (IVL_LPM_LATCH)
1318+
* This device is an asynchronous latch. The ivl_lpm_q output and
1319+
* single ivl_lpm_data input are the same width, ivl_lpm_width. This
13141320
* device carries a vector like other LPM devices.
13151321
*
13161322
* - Memory port (IVL_LPM_RAM) (deprecated in favor of IVL_LPM_ARRAY)
@@ -1428,18 +1434,18 @@ extern unsigned ivl_lpm_negedge(ivl_lpm_t net);
14281434
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
14291435
/* IVL_LPM_UFUNC */
14301436
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
1431-
/* IVL_LPM_FF */
1437+
/* IVL_LPM_FF IVL_LPM_LATCH*/
14321438
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
14331439
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
14341440
IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
1435-
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE */
1441+
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE IVL_LPM_LATCH */
14361442
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
14371443
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB IVL_LPM_CMP_EQ
14381444
IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE */
14391445
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
14401446
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
14411447
IVL_LPM_SUB IVL_LPM_UFUNC IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX
1442-
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE */
1448+
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE IVL_LPM_LATCH */
14431449
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net);
14441450
extern ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net);
14451451
extern ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net);

netlist.cc

+54
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,60 @@ const verinum& NetFF::sset_value() const
13061306
return sset_value_;
13071307
}
13081308

1309+
/*
1310+
* The NetLatch class represents an LPM_LATCH device. The pinout is assigned
1311+
* like so:
1312+
* 0 -- Enable
1313+
* 1 -- Data
1314+
* 2 -- Q
1315+
*/
1316+
1317+
NetLatch::NetLatch(NetScope*s, perm_string n, unsigned width__)
1318+
: NetNode(s, n, 3), width_(width__)
1319+
{
1320+
pin_Enable().set_dir(Link::INPUT);
1321+
pin_Data().set_dir(Link::INPUT);
1322+
pin_Q().set_dir(Link::OUTPUT);
1323+
}
1324+
1325+
NetLatch::~NetLatch()
1326+
{
1327+
}
1328+
1329+
unsigned NetLatch::width() const
1330+
{
1331+
return width_;
1332+
}
1333+
1334+
Link& NetLatch::pin_Enable()
1335+
{
1336+
return pin(0);
1337+
}
1338+
1339+
const Link& NetLatch::pin_Enable() const
1340+
{
1341+
return pin(0);
1342+
}
1343+
1344+
Link& NetLatch::pin_Data()
1345+
{
1346+
return pin(1);
1347+
}
1348+
1349+
const Link& NetLatch::pin_Data() const
1350+
{
1351+
return pin(1);
1352+
}
1353+
1354+
Link& NetLatch::pin_Q()
1355+
{
1356+
return pin(2);
1357+
}
1358+
1359+
const Link& NetLatch::pin_Q() const
1360+
{
1361+
return pin(2);
1362+
}
13091363

13101364
NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
13111365
: NetNode(s, n, 2), width_(w)

netlist.h

+29
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,35 @@ class NetFF : public NetNode {
16841684
verinum sset_value_;
16851685
};
16861686

1687+
1688+
/*
1689+
* This class represents an LPM_LATCH device. There is no literal gate
1690+
* type in Verilog that maps, but gates of this type can be inferred.
1691+
*/
1692+
class NetLatch : public NetNode {
1693+
1694+
public:
1695+
NetLatch(NetScope*s, perm_string n, unsigned vector_width);
1696+
~NetLatch();
1697+
1698+
unsigned width() const;
1699+
1700+
Link& pin_Enable();
1701+
Link& pin_Data();
1702+
Link& pin_Q();
1703+
1704+
const Link& pin_Enable() const;
1705+
const Link& pin_Data() const;
1706+
const Link& pin_Q() const;
1707+
1708+
virtual void dump_node(ostream&, unsigned ind) const;
1709+
virtual bool emit_node(struct target_t*) const;
1710+
virtual void functor_node(Design*des, functor_t*fun);
1711+
1712+
private:
1713+
unsigned width_;
1714+
};
1715+
16871716
/*
16881717
* This class implements a basic LPM_MULT combinational multiplier. It
16891718
* is used as a structural representation of the * operator. The

0 commit comments

Comments
 (0)