Synthesis rework.

Synthesis could only handle relatively simple conditional constructs.
This rework aims to make it handle anything the user can throw at it
(or output a sensible message as to why it can't).
This commit is contained in:
Martin Whitaker 2016-02-20 23:52:00 +00:00
parent 46105e0c5a
commit 5286fb858d
5 changed files with 986 additions and 701 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -311,6 +311,20 @@ void Nexus::count_io(unsigned&inp, unsigned&out) const
}
}
bool Nexus::has_floating_input() const
{
bool found_input = false;
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
if (cur->get_dir() == Link::OUTPUT)
return false;
if (cur->get_dir() == Link::INPUT)
found_input = true;
}
return found_input;
}
bool Nexus::drivers_present() const
{
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
@ -467,6 +481,17 @@ NetNet* Nexus::pick_any_net()
return 0;
}
NetNode* Nexus::pick_any_node()
{
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
NetNode*node = dynamic_cast<NetNode*>(cur->get_obj());
if (node != 0)
return node;
}
return 0;
}
const char* Nexus::name() const
{
if (name_)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -23,6 +23,7 @@
# include "netlist.h"
# include "netclass.h"
# include "netenum.h"
# include "netvector.h"
# include <cstring>
# include <cstdlib>
# include <sstream>
@ -161,6 +162,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
lineno_ = 0;
def_lineno_ = 0;
genvar_tmp_val = 0;
tie_hi_ = 0;
tie_lo_ = 0;
}
NetScope::~NetScope()
@ -744,3 +747,33 @@ perm_string NetScope::local_symbol()
res << "_s" << (lcounter_++);
return lex_strings.make(res.str());
}
void NetScope::add_tie_hi(Design*des)
{
if (tie_hi_ == 0) {
NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC1"),
NetNet::WIRE, &netvector_t::scalar_logic);
sig->local_flag(true);
tie_hi_ = new NetLogic(this, local_symbol(),
1, NetLogic::PULLUP, 1);
des->add_node(tie_hi_);
connect(sig->pin(0), tie_hi_->pin(0));
}
}
void NetScope::add_tie_lo(Design*des)
{
if (tie_lo_ == 0) {
NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC0"),
NetNet::WIRE, &netvector_t::scalar_logic);
sig->local_flag(true);
tie_lo_ = new NetLogic(this, local_symbol(),
1, NetLogic::PULLDOWN, 1);
des->add_node(tie_lo_);
connect(sig->pin(0), tie_lo_->pin(0));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -1022,11 +1022,36 @@ NetProc::~NetProc()
NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
: type_(t), statement_(st), scope_(s)
{
synthesized_design_ = 0;
}
NetProcTop::~NetProcTop()
{
if (!synthesized_design_) {
delete statement_;
return;
}
NexusSet nex_set;
statement_->nex_output(nex_set);
delete statement_;
bool flag = false;
for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) {
NetNet*net = nex_set[idx].lnk.nexus()->pick_any_net();
if (net->peek_lref() > 0) {
cerr << get_fileline() << ": warning: '" << net->name()
<< "' is driven by more than one process." << endl;
flag = true;
}
}
if (flag) {
cerr << get_fileline() << ": sorry: Cannot synthesize signals "
"that are driven by more than one process." << endl;
synthesized_design_->errors += 1;
}
}
NetProc* NetProcTop::statement()

View File

@ -1,7 +1,7 @@
#ifndef IVL_netlist_H
#define IVL_netlist_H
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -379,6 +379,8 @@ class Nexus {
NetNet* pick_any_net();
NetNode* pick_any_node();
/* This method counts the number of input and output links for
this nexus, and assigns the results to the output arguments. */
void count_io(unsigned&inp, unsigned&out) const;
@ -388,6 +390,10 @@ class Nexus {
is a variable, but also if this is a net with a force. */
bool assign_lval() const;
/* This method returns true if there are any inputs
attached to this nexus but no drivers. */
bool has_floating_input() const;
/* This method returns true if there are any drivers
(including variables) attached to this nexus. */
bool drivers_present() const;
@ -1146,6 +1152,12 @@ class NetScope : public Definitions, public Attrib {
children of this node as well. */
void run_functor(Design*des, functor_t*fun);
/* These are used in synthesis. They provide shared pullup and
pulldown nodes for this scope. */
void add_tie_hi(Design*des);
void add_tie_lo(Design*des);
Link&tie_hi() const { return tie_hi_->pin(0); };
Link&tie_lo() const { return tie_lo_->pin(0); };
/* This member is used during elaboration to pass defparam
assignments from the scope pass to the parameter evaluation
@ -1267,6 +1279,9 @@ class NetScope : public Definitions, public Attrib {
/* Final procedures sets this to notify statements that
they are part of a final procedure. */
bool in_final_;
NetNode*tie_hi_;
NetNode*tie_lo_;
};
/*
@ -2605,12 +2620,11 @@ class NetProc : public virtual LineInfo {
// Synthesize as asynchronous logic, and return true. The
// nex_out is where this function attaches its output
// results. The accumulated_nex_out is used by sequential
// blocks to show outputs from the previous code.
// results.
typedef vector<bool> mask_t;
virtual bool synth_async(Design*des, NetScope*scope,
NexusSet&nex_map,
NetBus&nex_out,
NetBus&accumulated_nex_out);
NexusSet&nex_map, NetBus&nex_out,
NetBus&enables, vector<mask_t>&bitmasks);
// Synthesize as synchronous logic, and return true. That
// means binding the outputs to the data port of a FF, and the
@ -2630,6 +2644,7 @@ class NetProc : public virtual LineInfo {
NetBus&ff_aclr, NetBus&ff_aset,
vector<verinum>&ff_aset_value,
NexusSet&nex_map, NetBus&nex_out,
vector<mask_t>&bitmasks,
const std::vector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;
@ -2640,7 +2655,9 @@ class NetProc : public virtual LineInfo {
protected:
bool synth_async_block_substatement_(Design*des, NetScope*scope,
NexusSet&nex_map,
NetBus&accumulated_nex_out,
NetBus&nex_out,
NetBus&enables,
vector<mask_t>&bitmasks,
NetProc*substmt);
private:
friend class NetBlock;
@ -2819,7 +2836,7 @@ class NetAssignBase : public NetProc {
bool synth_async(Design*des, NetScope*scope,
NexusSet&nex_map, NetBus&nex_out,
NetBus&accumulated_nex_out);
NetBus&enables, vector<mask_t>&bitmasks);
// This dumps all the lval structures.
void dump_lval(ostream&) const;
@ -2905,7 +2922,7 @@ class NetBlock : public NetProc {
// synthesize as asynchronous logic, and return true.
bool synth_async(Design*des, NetScope*scope,
NexusSet&nex_map, NetBus&nex_out,
NetBus&accumulated_nex_out);
NetBus&enables, vector<mask_t>&bitmasks);
bool synth_sync(Design*des, NetScope*scope,
bool&ff_negedge,
@ -2913,6 +2930,7 @@ class NetBlock : public NetProc {
NetBus&ff_aclr,NetBus&ff_aset,
vector<verinum>&ff_aset_value,
NexusSet&nex_map, NetBus&nex_out,
vector<mask_t>&bitmasks,
const std::vector<NetEvProbe*>&events);
// This version of emit_recurse scans all the statements of
@ -2968,7 +2986,7 @@ class NetCase : public NetProc {
bool synth_async(Design*des, NetScope*scope,
NexusSet&nex_map, NetBus&nex_out,
NetBus&accumulated_nex_out);
NetBus&enables, vector<mask_t>&bitmasks);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
@ -2984,7 +3002,7 @@ class NetCase : public NetProc {
bool synth_async_casez_(Design*des, NetScope*scope,
NexusSet&nex_map, NetBus&nex_out,
NetBus&accumulated_nex_out);
NetBus&enables, vector<mask_t>&bitmasks);
TYPE type_;
@ -3048,7 +3066,7 @@ class NetCondit : public NetProc {
bool is_asynchronous();
bool synth_async(Design*des, NetScope*scope,
NexusSet&nex_map, NetBus&nex_out,
NetBus&accumulated_nex_out);
NetBus&enables, vector<mask_t>&bitmasks);
bool synth_sync(Design*des, NetScope*scope,
bool&ff_negedge,
@ -3056,6 +3074,7 @@ class NetCondit : public NetProc {
NetBus&ff_aclr,NetBus&ff_aset,
vector<verinum>&ff_aset_value,
NexusSet&nex_map, NetBus&nex_out,
vector<mask_t>&bitmasks,
const std::vector<NetEvProbe*>&events);
virtual bool emit_proc(struct target_t*) const;
@ -3327,7 +3346,7 @@ class NetEvWait : public NetProc {
virtual bool synth_async(Design*des, NetScope*scope,
NexusSet&nex_map, NetBus&nex_out,
NetBus&accumulated_nex_out);
NetBus&enables, vector<mask_t>&bitmasks);
virtual bool synth_sync(Design*des, NetScope*scope,
bool&ff_negedge,
@ -3335,6 +3354,7 @@ class NetEvWait : public NetProc {
NetBus&ff_aclr,NetBus&ff_aset,
vector<verinum>&ff_aset_value,
NexusSet&nex_map, NetBus&nex_out,
vector<mask_t>&bitmasks,
const std::vector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;
@ -3439,7 +3459,7 @@ class NetForLoop : public NetProc {
// synthesize as asynchronous logic, and return true.
bool synth_async(Design*des, NetScope*scope,
NexusSet&nex_map, NetBus&nex_out,
NetBus&accumulated_nex_out);
NetBus&enables, vector<mask_t>&bitmasks);
private:
NetNet*index_;
@ -3827,8 +3847,14 @@ class NetProcTop : public LineInfo, public Attrib {
bool emit(struct target_t*tgt) const;
private:
bool tie_off_floating_inputs_(Design*des,
NexusSet&nex_map, NetBus&nex_in,
vector<NetProc::mask_t>&bitmasks,
bool is_ff_input);
const ivl_process_type_t type_;
NetProc*const statement_;
Design*synthesized_design_;
NetScope*scope_;
friend class Design;

1544
synth2.cc

File diff suppressed because it is too large Load Diff