Skip to content

Commit

Permalink
signed vs unsigned port connection
Browse files Browse the repository at this point in the history
  • Loading branch information
alaindargelas committed Nov 8, 2023
1 parent 91616db commit 5424d49
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- mode:cmake -*-
cmake_minimum_required(VERSION 3.20 FATAL_ERROR)

project(UHDM VERSION 1.77)
project(UHDM VERSION 1.78)

# Detect build type, fallback to release and throw a warning if use didn't
# specify any
Expand Down
4 changes: 3 additions & 1 deletion templates/Serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ enum ErrorType {
UHDM_UNSUPPORTED_TYPESPEC = 728,
UHDM_UNRESOLVED_PROPERTY = 729,
UHDM_NON_TEMPORAL_SEQUENCE_USE = 730,
UHDM_NON_POSITIVE_VALUE = 731
UHDM_NON_POSITIVE_VALUE = 731,
UHDM_SIGNED_UNSIGNED_PORT_CONN = 732,
UHDM_FORCING_UNSIGNED_TYPE = 733
};

#ifndef SWIG
Expand Down
67 changes: 67 additions & 0 deletions templates/SynthSubset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ namespace UHDM {

SynthSubset::SynthSubset(Serializer* serializer,
std::set<const any*>& nonSynthesizableObjects,
design* des,
bool reportErrors, bool allowFormal)
: serializer_(serializer),
nonSynthesizableObjects_(nonSynthesizableObjects),
design_(des),
reportErrors_(reportErrors),
allowFormal_(allowFormal) {
constexpr std::string_view kDollar("$");
Expand Down Expand Up @@ -395,5 +397,70 @@ void SynthSubset::leaveFor_stmt(const for_stmt* object, vpiHandle handle) {
}
}

void SynthSubset::leavePort(const port* object, vpiHandle handle) {
if (isInUhdmAllIterator()) return;
bool signedLowConn = false;
if (const any* lc = object->Low_conn()) {
if (const ref_obj* ref = any_cast<const ref_obj*>(lc)) {
if (const any* actual = ref->Actual_group()) {
if (actual->UhdmType() == uhdmlogic_var) {
logic_var* var = (logic_var*)actual;
if (var->VpiSigned()) {
signedLowConn = true;
}
}
if (actual->UhdmType() == uhdmlogic_net) {
logic_net* var = (logic_net*)actual;
if (var->VpiSigned()) {
signedLowConn = true;
}
}
}
}
}
if (signedLowConn) return;

std::string highConnSignal;
const any* reportObject = object;
if (const any* hc = object->High_conn()) {
if (const ref_obj* ref = any_cast<const ref_obj*> (hc)) {
reportObject = ref;
if (const any* actual = ref->Actual_group()) {
if (actual->UhdmType() == uhdmlogic_var) {
logic_var* var = (logic_var*)actual;
if (var->VpiSigned()) {
highConnSignal = actual->VpiName();
var->VpiSigned(false);
if (const ref_typespec* tps = var->Typespec()) {
if (const logic_typespec* ltps =
any_cast<const logic_typespec*>(tps->Actual_typespec())) {
((logic_typespec*)ltps)->VpiSigned(false);
}
}
}
}
if (actual->UhdmType() == uhdmlogic_net) {
logic_net* var = (logic_net*)actual;
if (var->VpiSigned()) {
highConnSignal = actual->VpiName();
var->VpiSigned(false);
if (const ref_typespec* tps = var->Typespec()) {
if (const logic_typespec* ltps =
any_cast<const logic_typespec*>(tps->Actual_typespec())) {
((logic_typespec*)ltps)->VpiSigned(false);
}
}
}
}
}
}
}
if (!highConnSignal.empty()) {
const std::string errMsg(highConnSignal);
serializer_->GetErrorHandler()(ErrorType::UHDM_FORCING_UNSIGNED_TYPE, errMsg,
reportObject, nullptr);
}

}

} // namespace UHDM
6 changes: 5 additions & 1 deletion templates/SynthSubset.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Serializer;
class SynthSubset final : public VpiListener {
public:
SynthSubset(Serializer* serializer,
std::set<const any*>& nonSynthesizableObjects, bool reportErrors, bool allowFormal);
std::set<const any*>& nonSynthesizableObjects, design* des, bool reportErrors, bool allowFormal);
~SynthSubset() override = default;
void filterNonSynthesizable();
void report(std::ostream& out);
Expand All @@ -62,13 +62,17 @@ class SynthSubset final : public VpiListener {
// Apply some rewrite rule for Yosys limitations
void leaveFor_stmt(const for_stmt* object, vpiHandle handle) override;

// Signed/Unsigned port transform to allow Yosys to Synthesize
void leavePort(const port* object, vpiHandle handle) override;

void reportError(const any* object);
void mark(const any* object);
bool reportedParent(const any* object);

Serializer* serializer_ = nullptr;
std::set<const any*>& nonSynthesizableObjects_;
std::set<std::string, std::less<>> nonSynthSysCalls_;
design* design_;
bool reportErrors_;
bool allowFormal_;
std::vector<std::pair<VectorOfany*, const any*>> m_scheduledFilteredObjects;
Expand Down
53 changes: 53 additions & 0 deletions templates/UhdmLint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,57 @@ void UhdmLint::leaveSys_func_call(const sys_func_call* object,
}
}


void UhdmLint::leavePort(const port* object, vpiHandle handle) {
if (isInUhdmAllIterator()) return;
bool signedHighConn = false;
bool signedLowConn = false;
bool highConn = false;
const any* reportObject = object;
if (const any* hc = object->High_conn()) {
if (const ref_obj* ref = any_cast<const ref_obj*> (hc)) {
reportObject = ref;
if (const any* actual = ref->Actual_group()) {
if (actual->UhdmType() == uhdmlogic_var) {
logic_var* var = (logic_var*)actual;
highConn = true;
if (var->VpiSigned()) {
signedHighConn = true;
}
} if (actual->UhdmType() == uhdmlogic_net) {
logic_net* var = (logic_net*)actual;
highConn = true;
if (var->VpiSigned()) {
signedHighConn = true;
}
}
}
}
}
if (const any* lc = object->Low_conn()) {
if (const ref_obj* ref = any_cast<const ref_obj*>(lc)) {
if (const any* actual = ref->Actual_group()) {
if (actual->UhdmType() == uhdmlogic_var) {
logic_var* var = (logic_var*)actual;
if (var->VpiSigned()) {
signedLowConn = true;
}
}
if (actual->UhdmType() == uhdmlogic_net) {
logic_net* var = (logic_net*)actual;
if (var->VpiSigned()) {
signedLowConn = true;
}
}
}
}
}
if (highConn && (signedLowConn != signedHighConn)) {
std::string_view errMsg = object->VpiName();
serializer_->GetErrorHandler()(
ErrorType::UHDM_SIGNED_UNSIGNED_PORT_CONN, std::string(errMsg),
reportObject, nullptr);
}
}

} // namespace UHDM
2 changes: 2 additions & 0 deletions templates/UhdmLint.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class UhdmLint final : public VpiListener {

void leaveSys_func_call(const sys_func_call* object, vpiHandle handle) override;

void leavePort(const port* object, vpiHandle handle) override;

void checkMultiContAssign(const std::vector<UHDM::cont_assign*>* assigns);

Serializer* serializer_ = nullptr;
Expand Down
8 changes: 7 additions & 1 deletion util/uhdm-lint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ int32_t main(int32_t argc, char **argv) {
case UHDM::UHDM_NON_POSITIVE_VALUE:
errmsg = "Non positive (<1) value";
break;
case UHDM::UHDM_SIGNED_UNSIGNED_PORT_CONN:
errmsg = "Signed vs Unsigned port connection";
break;
case UHDM::UHDM_FORCING_UNSIGNED_TYPE:
errmsg = "Critical: Forcing signal to unsigned type due to unsigned port binding ";
break;
}

if (object1) {
Expand All @@ -197,7 +203,7 @@ int32_t main(int32_t argc, char **argv) {

std::set<const UHDM::any*> nonSynthesizableObjects;
UHDM::SynthSubset* annotate = new UHDM::SynthSubset(
serializer.get(), nonSynthesizableObjects, true, true);
serializer.get(), nonSynthesizableObjects, design, true, true);
annotate->listenDesigns(designs);
delete annotate;

Expand Down

0 comments on commit 5424d49

Please sign in to comment.