Skip to content

Commit

Permalink
Move DriverMap implementation to drivertools.cc
Browse files Browse the repository at this point in the history
  • Loading branch information
RCoeurjoly committed May 23, 2024
1 parent 589fc40 commit c692e4f
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 131 deletions.
41 changes: 41 additions & 0 deletions kernel/drivertools.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2166,4 +2166,45 @@ const char *log_signal(DriveSpec const &spec)
return log_str(str);
}

DriverMap::DriverMap() : next_offset(1 + static_cast<int>(State::Sm))
{
celltypes.setup();
}

DriverMap::DriverMap(Design *design) : next_offset(1 + static_cast<int>(State::Sm))
{
celltypes.setup();
celltypes.setup_design(design);
}

DriverMap::DriveBitId::DriveBitId() : id(-1) {}

DriverMap::DriveBitId::DriveBitId(int id) : id(id) {}

bool DriverMap::DriveBitId::operator==(const DriveBitId &other) const
{
return id == other.id;
}

bool DriverMap::DriveBitId::operator!=(const DriveBitId &other) const
{
return id != other.id;
}

bool DriverMap::DriveBitId::operator<(const DriveBitId &other) const
{
return id < other.id;
}

unsigned int DriverMap::DriveBitId::hash() const
{
return id;
}

bool DriverMap::keep_wire(Wire *wire) {
// TODO configurable
return wire->has_attribute(ID(keep));
}


YOSYS_NAMESPACE_END
200 changes: 69 additions & 131 deletions kernel/drivertools.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,122 +422,82 @@ struct DriveSpec

struct DriverMap
{
CellTypes celltypes;
CellTypes celltypes;

DriverMap() { celltypes.setup(); }
DriverMap(Design *design) { celltypes.setup(); celltypes.setup_design(design); }
DriverMap();
DriverMap(Design *design);

private:
struct DriveBitId
{
int id;

// Internally we represent all DriveBits by mapping them to DriveBitIds
// which use less memory and are cheaper to compare.
struct DriveBitId
{
int id = -1;

DriveBitId() {};

DriveBitId(int id) : id(id) { }

bool operator==(const DriveBitId &other) const { return id == other.id; }
bool operator!=(const DriveBitId &other) const { return id != other.id; }
bool operator<(const DriveBitId &other) const { return id < other.id; }
unsigned int hash() const { return id; }
};
// Essentially a dict<DriveBitId, pool<DriveBitId>> but using less memory
// and fewer allocations
struct DriveBitGraph {
dict<DriveBitId, DriveBitId> first_edges;
dict<DriveBitId, DriveBitId> second_edges;
dict<DriveBitId, pool<DriveBitId>> more_edges;

void add_edge(DriveBitId src, DriveBitId dst);
DriveBitId pop_edge(DriveBitId src);
void clear(DriveBitId src);
bool contains(DriveBitId src);
int count(DriveBitId src);

DriveBitId at(DriveBitId src, int index);
};
DriveBitId();
DriveBitId(int id);

// The following two maps maintain a sparse DriveBit to DriveBitId mapping.
// This saves a lot of memory compared to a `dict<DriveBit, DriveBitId>` or
// `idict<DriveBit>`.

// Maps wires to the first DriveBitId of the consecutive range used for
// that wire.
dict<Wire *, DriveBitId> wire_offsets;

// Maps cell ports to a the first DriveBitId of the consecutive range used
// for that cell port.
dict<pair<Cell *, IdString>, DriveBitId> port_offsets;

// For the inverse map that maps DriveBitIds back to DriveBits we use a
// sorted map containing only the first DriveBit for each wire and cell
// port.
std::map<DriveBitId, DriveBit> drive_bits;

// As a memory optimization for gate level net lists we store single-bit
// wires and cell ports in a `dict` which requires less memory and fewer
// allocations than `std::map` but doesn't support the kind of lookups we
// need for a sparse coarse grained mapping.
dict<DriveBitId, DriveBit> isolated_drive_bits;

// Used for allocating DriveBitIds, none and constant states use a fixewd
// mapping to the first few ids, which we need to skip.
int next_offset = 1 + (int)State::Sm;

// Union-Find over directly connected bits that share the same single
// driver or are undriven. We never merge connections between drivers
// and/or kept wires.
mfp<DriveBitId> same_driver;

// For each bit, store a set of connected driver bits for which the
// explicit connection should be preserved and the driving direction is
// locally unambiguous (one side only drives or requires a driven value).
DriveBitGraph connected_drivers;

// For each bit, store a set of connected driver bits for which the
// explicit connection should be preserved and the driving direction is
// locally ambiguous. Every such ambiguous connection is also present in
// the reverse direction and has to be resolved when querying drivers.
DriveBitGraph connected_undirected;

// Subset of `connected_undirected` for caching the resolved driving
// direction. In case multiple drivers are present this can still contain
// both orientations of a single connection, but for a single driver only
// one will be present.
DriveBitGraph connected_oriented;

// Stores for which bits we already resolved the orientation (cached in
// `connected_oriented`).
pool<DriveBitId> oriented_present;


enum class BitMode {
NONE = 0, // Not driven, no need to keep wire
DRIVEN = 1, // Not driven, uses a value driven elsewhere
DRIVEN_UNIQUE = 2, // Uses a value driven elsewhere, has at most one direct connection
KEEP = 3, // Wire that should be kept
TRISTATE = 4, // Can drive a value but can also use a value driven elsewhere
DRIVER = 5, // Drives a value
};
bool operator==(const DriveBitId &other) const;
bool operator!=(const DriveBitId &other) const;
bool operator<(const DriveBitId &other) const;
unsigned int hash() const;
};

BitMode bit_mode(DriveBit const &bit);
DriveBitId id_from_drive_bit(DriveBit const &bit);
DriveBit drive_bit_from_id(DriveBitId id);
struct DriveBitGraph
{
dict<DriveBitId, DriveBitId> first_edges;
dict<DriveBitId, DriveBitId> second_edges;
dict<DriveBitId, pool<DriveBitId>> more_edges;

void add_edge(DriveBitId src, DriveBitId dst);
DriveBitId pop_edge(DriveBitId src);
void clear(DriveBitId src);
bool contains(DriveBitId src);
int count(DriveBitId src);
DriveBitId at(DriveBitId src, int index);
};

void connect_directed_merge(DriveBitId driven_id, DriveBitId driver_id);
void connect_directed_buffer(DriveBitId driven_id, DriveBitId driver_id);
void connect_undirected(DriveBitId a_id, DriveBitId b_id);
dict<Wire *, DriveBitId> wire_offsets;
dict<pair<Cell *, IdString>, DriveBitId> port_offsets;
std::map<DriveBitId, DriveBit> drive_bits;
dict<DriveBitId, DriveBit> isolated_drive_bits;
int next_offset;
mfp<DriveBitId> same_driver;
DriveBitGraph connected_drivers;
DriveBitGraph connected_undirected;
DriveBitGraph connected_oriented;
pool<DriveBitId> oriented_present;

enum class BitMode
{
NONE = 0,
DRIVEN = 1,
DRIVEN_UNIQUE = 2,
KEEP = 3,
TRISTATE = 4,
DRIVER = 5,
};

BitMode bit_mode(DriveBit const &bit);
DriveBitId id_from_drive_bit(DriveBit const &bit);
DriveBit drive_bit_from_id(DriveBitId id);
void connect_directed_merge(DriveBitId driven_id, DriveBitId driver_id);
void connect_directed_buffer(DriveBitId driven_id, DriveBitId driver_id);
void connect_undirected(DriveBitId a_id, DriveBitId b_id);
void add_port(Cell *cell, IdString const &port, SigSpec const &b);
void orient_undirected(DriveBitId id);
bool keep_wire(Wire *wire);

// Only used a local variables in `orient_undirected`, always cleared, only
// stored to reduce allocations.
pool<DriveBitId> orient_undirected_seen;
pool<DriveBitId> orient_undirected_drivers;
dict<DriveBitId, int> orient_undirected_distance;


public:
void add(Module *module);
void add(DriveBit const &a, DriveBit const &b);

void add(Module *module);

// Add a single bit connection to the driver map.
void add(DriveBit const &a, DriveBit const &b);


template<typename T>
static constexpr bool is_sig_type() {
return
Expand All @@ -561,31 +521,9 @@ struct DriverMap
add(DriveBit(a[i]), DriveBit(b[i]));
}


// Specialized version that avoids unpacking
void add(SigSpec const &a, SigSpec const &b);

private:
void add_port(Cell *cell, IdString const &port, SigSpec const &b);

// Only used a local variables in `orient_undirected`, always cleared, only
// stored to reduce allocations.
pool<DriveBitId> orient_undirected_seen;
pool<DriveBitId> orient_undirected_drivers;
dict<DriveBitId, int> orient_undirected_distance;

void orient_undirected(DriveBitId id);

public:
DriveBit operator()(DriveBit const &bit);

DriveSpec operator()(DriveSpec spec);

private:
bool keep_wire(Wire *wire) {
// TODO configurable
return wire->has_attribute(ID(keep));
}
void add(SigSpec const &a, SigSpec const &b);
DriveBit operator()(DriveBit const &bit);
DriveSpec operator()(DriveSpec spec);
};

YOSYS_NAMESPACE_END
Expand Down

0 comments on commit c692e4f

Please sign in to comment.